package typistcal.storage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Vector;

import typistcal.userinterface.UserInterface;

//@author A0096911Y
public class FileOperator {
	private static final String MESSAGE_ERROR = "Error Message";
	private static final String MESSAGE_ERROR_INSERT = "Insertion Error!";
	private static final String NEWLINE = System.getProperty("line.separator");
	private static final String MESSAGE_ERROR_FILE_NOT_FOUND = "File not found!";
	private String fileName;
	private Vector<String> fileBuffer;
	
	public FileOperator(String fileName) {
		this.fileName = fileName;
		fileBuffer = new Vector<String>();
		
		try {
			if ( !isFileExists() ) {
				createFile();
			}
			loadFromFile();
		}
		catch (IOException e){
			System.out.println(MESSAGE_ERROR);
			e.printStackTrace();
		}
	}
	
	/*
	 * @return true if insert is successful
	 */
	public boolean insertIntoFile(String line, int lineNumber) {
		assert ( lineNumber >= 0 );
		try {
			fileBuffer.add(lineNumber, line);
			updateFileWithBuffer();
		} catch (Exception e) {
			UserInterface.displayToDisplayArea(MESSAGE_ERROR_INSERT);
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	/* 
	 * @return true if delete is successful and vice versa
	 */
	public boolean deleteFromFile(int lineNumber) {
		assert ( lineNumber >= 0 );
		try {
			fileBuffer.remove(lineNumber);
			updateFileWithBuffer();
			return true;
		}
		catch (Exception e) {
			return false;
		}
	}
	
	public Vector<Integer> findEntriesOfKeyword(String keyword) {
		Vector<Integer> listOfNumbers = new Vector<Integer>();

		loadBufferIfNotLoaded();
		for ( int i = 0; i < fileBuffer.size(); i++ ) {
			if ( fileBuffer.get(i).toLowerCase().contains(keyword.toLowerCase()) ) {
				listOfNumbers.add(i);
			}
			
		}
		
		return listOfNumbers;
	}
	public Vector<Integer> listOfTheFile() {
		Vector<Integer> listOfNumbers = new Vector<Integer>();

		loadBufferIfNotLoaded();
		for ( int i = 0; i < fileBuffer.size(); i++ ) {
			
				listOfNumbers.add(i);
		}
		
		return listOfNumbers;
	}
	
	//@author A0105493H
	public String getLineContent(Integer sequenceNo){
		return fileBuffer.get(sequenceNo.intValue());
	}
	
	public int getNumberOfLinesInFile(){
		return fileBuffer.size();
	}
	
	//@author A0096911Y
	private void createFile() throws IOException {
		updateFileWithBuffer();
		
	}

	private void loadFromFile() throws IOException {
		Vector<String> linesOfText = new Vector<String>();
	
		FileReader fr = new FileReader(fileName);
		BufferedReader textReader = new BufferedReader(fr);
	
		int noOfLines = countLinesInFile();
	
		while ( noOfLines != 0 ) {
			linesOfText.add( textReader.readLine() );
			noOfLines--;
		}
	
		textReader.close();
		
		fileBuffer = linesOfText;
	}

	private void updateFileWithBuffer() throws IOException {
		FileWriter fw = new FileWriter(fileName);
		PrintWriter textWriter = new PrintWriter(fw);
	
		if ( fileBuffer.isEmpty() == false ) {
			for ( int j = 0; j < fileBuffer.size(); j++ ) {
				if ( !fileBuffer.get(j).equals("") ) {
					textWriter.printf("%s" + "%n", fileBuffer.get(j));
				}
			}
		}
	
		textWriter.close();
	}

	private int countLinesInFile() throws IOException {
		FileReader fr = new FileReader(fileName);
		BufferedReader br = new BufferedReader(fr);
	
		int noOfLines = 0;
		@SuppressWarnings("unused")
		String line;
		
		while ( (line = br.readLine()) != null ) {
			noOfLines++;
		}
		br.close();
	
		return noOfLines;
	}
	

	private boolean isFileExists() {
		return (new File(fileName).exists());
	}

	private void loadBufferIfNotLoaded() {
		try {
			if ( countLinesInFile() != fileBuffer.size() ) {
				loadFromFile();
			}
		} catch (IOException e) {
			System.out.println(MESSAGE_ERROR);
			e.printStackTrace();
		}
	}

	public String readAll() {
		String textInFile = "";
		try {
			int linesInFile = countLinesInFile();
			if ( linesInFile != fileBuffer.size() ) {
				//error
			}
			else {
				for ( int i = 0; i < linesInFile; i++ ) {
					textInFile += fileBuffer.get(i) + NEWLINE;
				}
			}
			
		} catch (IOException e) {
			UserInterface.displayToDisplayArea( fileName + " " + MESSAGE_ERROR_FILE_NOT_FOUND);
			e.printStackTrace();
		}
		return textInFile;
	}
}
